// Copyright (C) 2012 Volkov Zachar
// This file is part of the "zAxis Game Engine".
// For conditions of distribution and use, see copyright notice zx_Common.hpp

#include "zx_Video.hpp"
#include "gl/glew.h"

namespace zx {

//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
Uniform::Uniform( const String& _name, 
                 UniformType _type, 
                 uint _loc, 
                 uint _unit, 
                 int _size_loc, 
                 int _invsize_loc, 
                 TextureType _sampler_type ) : m_name( _name )
                                             , m_type( _type )
                                             , m_location( _loc )
                                             , m_texture_unit( _unit )
                                             , m_sampler_type( _sampler_type )
                                             , m_synchronized( false )
                                             , m_sampler_size( 0.0f )
                                             , m_sampler_size_loc( _size_loc )
                                             , m_sampler_invsize_loc( _invsize_loc )
{
     SetValue( 0.0f );
}
//----------------------------------------------------------------------------//
void Uniform::_Synchronize( void )
{
     if( m_type == UT_SAMPLER )
     {
          Vector3 _size;

          VideoDriver::Instance()._SetTextureUnitState( m_texture_unit, m_sampler_type, m_value, _size );

          if( m_sampler_size != _size )
          {
               m_sampler_size = _size;

               // set SamplerX::size
               if( m_sampler_size_loc >= 0 )
               {
                    glUniform3fvARB( m_sampler_size_loc, 1, m_sampler_size.v );    
               }

               // set SamplerX::invsize
               if( m_sampler_invsize_loc >= 0 )
               {
                    glUniform3fvARB( m_sampler_invsize_loc, 1, ( 1.0f / m_sampler_size ).v );    
               }
          }

          m_synchronized = true;
     }
     else if( !m_synchronized )
     {
          switch( m_type )
          {
               case UT_FLOAT   : { glUniform1fvARB( m_location, 1, m_value.GetData() ); } break;
               case UT_VECTOR2 : { glUniform2fvARB( m_location, 1, m_value.GetData() ); } break;
               case UT_VECTOR3 : { glUniform3fvARB( m_location, 1, m_value.GetData() ); } break;
               case UT_VECTOR4 : { glUniform4fvARB( m_location, 1, m_value.GetData() ); } break;
               case UT_MATRIX3 : { glUniformMatrix3fvARB( m_location, 1, GL_TRUE, m_value.GetData() ); } break;
               case UT_MATRIX4 : { glUniformMatrix4fvARB( m_location, 1, GL_TRUE, m_value.GetData() ); } break;
          };

          m_synchronized = true;
     }
}
//----------------------------------------------------------------------------//
void Uniform::SetValue( const UniformValue& _value )
{
     if( m_value != _value )
     {
          switch( m_type )
          {
               case UT_FLOAT   : m_value = (float)_value; break;
               case UT_VECTOR2 : m_value = (Vector2)_value;  break;
               case UT_VECTOR3 : m_value = (Vector3)_value;  break;
               case UT_VECTOR4 : m_value = (Vector4)_value;  break;
               case UT_MATRIX3 : m_value = (Matrix3)_value;  break;
               case UT_MATRIX4 : m_value = (Matrix4)_value;  break;
               case UT_SAMPLER : m_value = (SamplerPtr)_value; break;
          };

          m_synchronized = false; 
     }
}
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//

} // namespace zx
